﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Collections.Concurrent;

namespace Inovout.Descriptor
{
    public class EnumDescriptor : TypeDescriptor
    {
        #region Private Field
        /// <summary>
        /// 标记
        /// </summary>
        private bool flag;

        #endregion

        #region Property

        public EnumItemDescriptor[] EnumItems
        {
            get
            {
                return base.Fields.Where(field => field is EnumItemDescriptor)
                    .Select(field => (EnumItemDescriptor)field).ToArray();

            }
        }

        /// <summary>
        /// 是否有多个特性标记
        /// </summary>
        public bool Flag
        {
            get
            {
                return flag;
            }
        }

        #endregion

        #region Indexr

        /// <summary>
        /// 根据枚举获取描述
        /// </summary>
        /// <param name="item"></param>
        /// <returns>描述</returns>
        public EnumItemDescriptor this[Enum item]
        {
            get
            {
                return EnumItems.Single(enumItem => enumItem.Value.Equals(item));
            }
        }
        public EnumItemDescriptor this[int enumIntValue]
        {
            get
            {
                return EnumItems.Single(enumItem => enumItem.Value.Equals(Enum.ToObject(this.ReflectionType, enumIntValue)));
            }
        }
        public EnumItemDescriptor this[string enumName]
        {
            get
            {
                return EnumItems.Single(enumItem => enumItem.Name.Equals(enumName));
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// 初始化 EnumDescriptor类的新实例。
        /// </summary>
        /// <param name="enumType">枚举声明类型</param>
        internal EnumDescriptor(Type enumType)
            : base(enumType)
        {
            ArgumentAssert.IsEnumType(enumType, "enumType");

            flag = enumType.IsDefined(typeof(FlagsAttribute), false);

        }

        #endregion

        protected override FieldDescriptor CreateFieldDescriptor(FieldInfo fieldInfo)
        {
            //Enum会动态增长一个value_
            if (fieldInfo.IsLiteral)
            {
                return new EnumItemDescriptor(fieldInfo);
            }
            else
            {
                return base.CreateFieldDescriptor(fieldInfo);
            }
        }

        #region Method
        public new static EnumDescriptor Get(Type enumType)
        {
            ArgumentAssert.IsEnumType(enumType, "enumType");
            return TypeDescriptor.Get(enumType) as EnumDescriptor;
        }

        public new static EnumDescriptor Get<TEnum>() where TEnum : struct
        {

            return Get(typeof(TEnum));
        }
        #endregion

        public Enum GetEnum(string value)
        {
            return (this[value].Value);
        }
    }

    public static class EnumExtenssions
    {
        public static string ToAlias(this Enum value)
        {
            return EnumDescriptor.Get(value.GetType())[value].Alias;
        }

    }
}

